
package cn.zlg.common.datadump.util;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

import com.querydsl.core.types.Path;
import com.querydsl.core.types.dsl.EntityPathBase;

public class QueryDslUtils {

    public static EntityPathBase findQEntityInstance(Class entity)
            throws IllegalArgumentException, IllegalAccessException {
        Field[] fields = entity.getDeclaredFields();
        for (Field f : fields) {
            if (Modifier.isPublic(f.getModifiers()) && Modifier.isStatic(f.getModifiers()) && f.getType() == entity) {
                return (EntityPathBase) f.get(entity);
            }
        }
        return null;
    }

    public static Path findQPath(Class entity, String field) throws Exception {
        Object qEntityInstance = findQEntityInstance(entity);
        return (Path) extractChainValueFromArg(qEntityInstance, field);
    }

    public static Path findQPath(EntityPathBase entity, String field) throws Exception {
        return (Path) extractChainValueFromArg(entity, field);
    }

    /**
     * 获取形如a.b.c多层次对象值, 首先从a对象中取b属性值，再从该值中取c属性值。如果有一环为null或属性不存在，返回null。
     * 
     * @param object
     * @param queryObjectParams
     * @return
     * @throws Exception
     */
    public static Object extractChainValueFromArg(Object object, String queryObjectParams) throws Exception {
        if (object == null) {
            return object;
        }
        int i = queryObjectParams.indexOf('.');
        if (i == -1) {
            return getChainPropertyValue(object, queryObjectParams);
        }
        String[] ladders = queryObjectParams.split("\\.");
        for (int j = 0; j < ladders.length; j++) {
            object = getChainPropertyValue(object, ladders[j]);
            if (object == null) {
                return null;
            }
        }
        // 获取链式值
        return object;
    }

    private static Object getChainPropertyValue(Object object, String substring) throws Exception {
        Field field;
        field = object.getClass().getField(substring);
        field.setAccessible(true);
        return field.get(object);
    }
}
